import sys
import os
import logging
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QAction, QFileDialog,
                             QVBoxLayout, QHBoxLayout, QWidget, QToolBar, QStatusBar,
                             QPushButton, QMessageBox, QSplitter)
from PyQt5.QtGui import (QPixmap, QImage, QPainter, QTransform, QPen, QColor,
                         QFont, QPainterPath, QBrush)
from PyQt5.QtCore import Qt, QPoint, QRect, QRectF, QSize, QEvent, pyqtSignal, QObject

# 配置日志
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)


class CoordinateImageLabel(QLabel):
    # 定义缩放信号
    zoomRequested = pyqtSignal(float)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.pixmap = None
        self.show_coordinates = True
        self.mouse_pos = None
        self.image_rect = None  # 当前显示图片的矩形区域
        self.image_loaded = False  # 标记图像是否已加载

        # 圆形裁剪控件参数
        self.crop_enabled = False
        self.crop_radius = 120  # 直径240像素，半径120像素
        self.crop_center = QPoint(0, 0)
        self.dragging = False
        self.drag_start_pos = QPoint(0, 0)

        # 启用鼠标追踪
        self.setMouseTracking(True)

    def setPixmap(self, pixmap):
        # 释放之前的像素图资源
        if self.pixmap:
            self.pixmap = None

        self.pixmap = pixmap
        self.image_loaded = pixmap is not None  # 更新图像加载状态
        super().setPixmap(pixmap)

        # 添加调试日志
        if self.image_loaded:
            logger.debug(f"图像已加载 - 尺寸: {pixmap.width()}x{pixmap.height()}")
        else:
            logger.debug("图像未加载")

    def setImageRect(self, rect):
        self.image_rect = rect
        # 默认将裁剪中心设置为图像中心
        if rect:
            self.crop_center = QPoint(rect.center().x(), rect.center().y())
        self.update()

    def enableCrop(self, enable):
        self.crop_enabled = enable
        self.update()

    def paintEvent(self, event):
        try:
            super().paintEvent(event)

            if not self.pixmap:
                return

            painter = QPainter(self)
            painter.setRenderHint(QPainter.Antialiasing)

            # 绘制坐标系
            if self.show_coordinates and self.image_rect:
                # 设置画笔
                pen = QPen()
                pen.setWidth(1)
                pen.setColor(QColor(255, 0, 0))  # 红色坐标轴
                painter.setPen(pen)

                # 获取图像尺寸和位置
                label_rect = self.rect()

                # 计算图像在标签中的位置
                x = self.image_rect.x()
                y = self.image_rect.y()
                width = self.image_rect.width()
                height = self.image_rect.height()

                # 绘制坐标轴
                origin_x = x  # 左下角为原点
                origin_y = y + height

                # 绘制X轴（水平向右）
                painter.drawLine(origin_x, origin_y, origin_x + width, origin_y)

                # 绘制Y轴（竖直向上）
                painter.drawLine(origin_x, origin_y, origin_x, origin_y - height)

                # 绘制原点标记
                painter.setPen(Qt.NoPen)
                painter.setBrush(QColor(255, 0, 0))
                painter.drawEllipse(QPoint(origin_x, origin_y), 3, 3)

                # 绘制坐标刻度和标签
                painter.setPen(pen)
                font = QFont()
                font.setPointSize(8)
                painter.setFont(font)

                # X轴刻度和标签
                for i in range(0, width, 50):
                    if i != 0:  # 跳过原点
                        painter.drawLine(origin_x + i, origin_y - 5, origin_x + i, origin_y + 5)
                        painter.drawText(origin_x + i - 10, origin_y + 20, f"{i}")

                # Y轴刻度和标签（注意Y轴方向是向上的）
                for i in range(0, height, 50):
                    if i != 0:  # 跳过原点
                        painter.drawLine(origin_x - 5, origin_y - i, origin_x + 5, origin_y - i)
                        painter.drawText(origin_x - 30, origin_y - i + 5, f"{i}")

                # 显示鼠标位置的坐标
                if self.mouse_pos:
                    # 计算鼠标在图像中的坐标（相对于左下角原点）
                    image_x = self.mouse_pos.x() - origin_x
                    image_y = origin_y - self.mouse_pos.y()

                    painter.setPen(QPen(QColor(0, 0, 255), 1))  # 蓝色坐标文本
                    painter.drawText(10, 20, f"图像坐标: ({image_x}, {image_y})")

            # 绘制圆形裁剪控件
            if self.crop_enabled and self.image_rect:
                # 设置裁剪控件画笔和画刷
                pen = QPen()
                pen.setWidth(2)
                pen.setColor(QColor(0, 255, 0, 200))  # 半透明绿色边框
                painter.setPen(pen)

                # 绘制高透明的圆形裁剪区域
                brush = QBrush(QColor(0, 255, 0, 30))  # 高透明绿色填充
                painter.setBrush(brush)
                painter.drawEllipse(self.crop_center, self.crop_radius, self.crop_radius)

                # 绘制中心点标记
                painter.setPen(Qt.NoPen)
                painter.setBrush(QColor(0, 255, 0, 200))  # 半透明绿色中心点
                painter.drawEllipse(self.crop_center, 3, 3)

                # 显示裁剪中心坐标
                if self.image_rect:
                    rect = self.image_rect
                    origin_x = rect.x()
                    origin_y = rect.y() + rect.height()

                    crop_x = self.crop_center.x() - origin_x
                    crop_y = origin_y - self.crop_center.y()

                    painter.setPen(QPen(QColor(0, 255, 0, 200), 1))  # 半透明绿色坐标文本
                    painter.drawText(10, 40, f"裁剪中心: ({crop_x}, {crop_y})")
        except Exception as e:
            logger.error(f"绘制错误: {str(e)}")
            QMessageBox.critical(self, "绘制错误", f"绘制过程中发生错误:\n{str(e)}")

    def mousePressEvent(self, event):
        if self.crop_enabled and self.image_rect and self.image_loaded:
            # 检查是否点击了裁剪圆
            if (event.pos() - self.crop_center).manhattanLength() <= self.crop_radius:
                self.dragging = True
                self.drag_start_pos = event.pos()
                logger.debug("开始拖动裁剪区域")

        # 确保父类方法也被调用
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        # 更新鼠标位置
        self.mouse_pos = event.pos()

        if self.dragging and self.image_rect and self.image_loaded:
            # 计算移动量
            delta = event.pos() - self.drag_start_pos
            self.drag_start_pos = event.pos()

            # 更新裁剪中心位置
            self.crop_center += delta

            # 修改裁剪圆位置限制，允许边缘与图像边缘对齐
            rect = self.image_rect
            # 允许裁剪圆中心移动到距离边缘至少0的位置（即圆边缘可以与图像边缘对齐）
            min_x = rect.x()
            max_x = rect.x() + rect.width()
            min_y = rect.y()
            max_y = rect.y() + rect.height()

            # 限制裁剪中心，使圆的边缘可以与图像边缘对齐
            self.crop_center.setX(max(min_x, min(self.crop_center.x(), max_x)))
            self.crop_center.setY(max(min_y, min(self.crop_center.y(), max_y)))

            logger.debug(f"拖动裁剪区域到位置: {self.crop_center.x()}, {self.crop_center.y()}")
            self.update()

        # 确保父类方法也被调用
        super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if self.dragging:
            self.dragging = False
            logger.debug("结束拖动裁剪区域")

        # 确保父类方法也被调用
        super().mouseReleaseEvent(event)

    def wheelEvent(self, event):
        try:
            logger.debug("处理鼠标滚轮事件")

            # 检查父窗口是否存在
            if not self.parent():
                logger.warning("无法执行缩放操作：父窗口不存在")
                return

            # 检查图像是否已加载
            if not self.image_loaded or not self.pixmap or self.pixmap.isNull():
                logger.warning(
                    f"无法执行缩放操作：图像未加载 - 图像状态: {self.image_loaded}, pixmap: {self.pixmap is not None}")
                if hasattr(self.parent(), 'statusBar') and self.parent().statusBar:
                    self.parent().statusBar.showMessage("请先加载图片", 2000)
                return

            # 获取滚轮方向和缩放因子
            delta = event.angleDelta().y()
            if delta > 0:
                # 向上滚动 - 放大
                logger.debug("鼠标滚轮向上滚动，执行放大操作")
                self.zoomRequested.emit(1.1)
            else:
                # 向下滚动 - 缩小
                logger.debug("鼠标滚轮向下滚动，执行缩小操作")
                self.zoomRequested.emit(0.9)

        except Exception as e:
            logger.error(f"处理鼠标滚轮事件时发生错误: {str(e)}")
            QMessageBox.critical(self, "错误", f"缩放图像时发生错误:\n{str(e)}")


class ImageViewer(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

        # 初始化变量
        self.pixmap = None
        self.original_pixmap = None
        self.scale_factor = 1.0
        self.rotation_angle = 0
        self.image_path = None
        self.cropped_pixmap = None

        # 添加调试日志
        logger.debug("图片查看器初始化完成")

    def initUI(self):
        # 设置窗口标题和大小
        self.setWindowTitle('图片查看器')
        self.setGeometry(100, 100, 1200, 600)  # 增加窗口宽度以容纳右侧面板

        # 创建菜单栏
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('文件')

        # 创建打开文件动作
        openAction = QAction('打开', self)
        openAction.setShortcut('Ctrl+O')
        openAction.triggered.connect(self.openImage)
        fileMenu.addAction(openAction)

        # 创建工具栏
        toolbar = QToolBar("工具栏")
        self.addToolBar(toolbar)

        # 添加工具栏按钮
        zoomInAction = QAction('放大', self)
        zoomInAction.triggered.connect(lambda: self.zoom(1.25))
        toolbar.addAction(zoomInAction)

        zoomOutAction = QAction('缩小', self)
        zoomOutAction.triggered.connect(lambda: self.zoom(0.8))
        toolbar.addAction(zoomOutAction)

        rotateLeftAction = QAction('左转', self)
        rotateLeftAction.triggered.connect(lambda: self.rotate(-90))
        toolbar.addAction(rotateLeftAction)

        rotateRightAction = QAction('右转', self)
        rotateRightAction.triggered.connect(lambda: self.rotate(90))
        toolbar.addAction(rotateRightAction)

        # 切换坐标系显示
        toggleCoordsAction = QAction('显示/隐藏坐标系', self)
        toggleCoordsAction.triggered.connect(self.toggleCoordinates)
        toggleCoordsAction.setCheckable(True)
        toggleCoordsAction.setChecked(True)
        toolbar.addAction(toggleCoordsAction)

        # 启用/禁用裁剪功能
        toggleCropAction = QAction('启用/禁用裁剪', self)
        toggleCropAction.triggered.connect(self.toggleCrop)
        toggleCropAction.setCheckable(True)
        toggleCropAction.setChecked(False)
        toolbar.addAction(toggleCropAction)

        # 裁剪按钮
        cropAction = QAction('裁剪', self)
        cropAction.triggered.connect(self.cropImage)
        toolbar.addAction(cropAction)

        # 创建主窗口部件
        main_widget = QWidget()
        self.setCentralWidget(main_widget)

        # 创建分割器
        splitter = QSplitter(Qt.Horizontal)

        # 左侧面板 - 原始图像
        left_panel = QWidget()
        left_layout = QVBoxLayout(left_panel)

        # 创建图像显示区域（使用自定义的CoordinateImageLabel）
        self.image_label = CoordinateImageLabel()  # 不再传递父对象
        self.image_label.setAlignment(Qt.AlignCenter)
        self.image_label.setMinimumSize(1, 1)  # 允许标签缩小
        self.image_label.setStyleSheet("background-color: #f0f0f0;")
        self.image_label.show_coordinates = True

        # 连接缩放信号到槽函数
        self.image_label.zoomRequested.connect(self.zoom)

        # 右侧面板 - 裁剪结果
        right_panel = QWidget()
        right_layout = QVBoxLayout(right_panel)

        # 裁剪结果标题
        self.crop_result_title = QLabel("裁剪结果")
        self.crop_result_title.setAlignment(Qt.AlignCenter)
        self.crop_result_title.setStyleSheet("font-weight: bold; font-size: 14px; margin: 5px;")

        # 裁剪结果显示区域
        self.crop_result_label = QLabel()
        self.crop_result_label.setAlignment(Qt.AlignCenter)
        self.crop_result_label.setStyleSheet("background-color: #f0f0f0; border: 1px solid #ddd;")
        self.crop_result_label.setMinimumSize(300, 300)

        # 保存按钮
        self.save_button = QPushButton("保存裁剪结果")
        self.save_button.clicked.connect(self.saveCroppedImage)
        self.save_button.setEnabled(False)  # 初始禁用
        self.save_button.setStyleSheet("padding: 8px; margin: 10px 0;")

        # 添加控件到右侧布局
        right_layout.addWidget(self.crop_result_title)
        right_layout.addWidget(self.crop_result_label, 1)
        right_layout.addWidget(self.save_button)

        # 添加控件到左侧布局
        left_layout.addWidget(self.image_label, 1)

        # 创建信息显示区域
        info_layout = QHBoxLayout()
        self.original_size_label = QLabel("原始尺寸: -- x --")
        self.current_size_label = QLabel("当前尺寸: -- x --")
        self.position_label = QLabel("位置: --, --")

        info_layout.addWidget(self.original_size_label)
        info_layout.addWidget(self.current_size_label)
        info_layout.addWidget(self.position_label)
        left_layout.addLayout(info_layout)

        # 添加左右面板到分割器
        splitter.addWidget(left_panel)
        splitter.addWidget(right_panel)

        # 设置分割器初始大小
        splitter.setSizes([800, 400])

        # 创建状态栏
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)

        # 添加分割器到主布局
        main_layout = QVBoxLayout(main_widget)
        main_layout.addWidget(splitter)

        # 初始状态下禁用缩放和旋转操作
        self.setEnabledActions(False)

    def openImage(self):
        # 添加调试日志
        logger.debug("打开文件对话框被触发")

        # 打开文件对话框
        file_path, _ = QFileDialog.getOpenFileName(self, "打开图片", "", "图片文件 (*.jpg *.jpeg *.png *.bmp *.gif)")

        if file_path:
            logger.debug(f"选择的文件: {file_path}")
            self.image_path = file_path
            self.loadImage(file_path)

            # 清除之前的裁剪结果
            self.clearCropResult()

    def clearCropResult(self):
        """清除裁剪结果显示"""
        self.crop_result_label.clear()
        self.cropped_pixmap = None
        self.save_button.setEnabled(False)
        self.statusBar.showMessage("裁剪结果已清除", 3000)

    def loadImage(self, file_path):
        # 添加调试日志
        logger.debug(f"加载图片: {file_path}")

        try:
            # 加载图片
            self.original_pixmap = QPixmap(file_path)
            if self.original_pixmap.isNull():
                self.statusBar.showMessage("无法加载图片", 3000)
                logger.error("图片加载失败")
                QMessageBox.critical(self, "加载错误", "无法加载图片，请检查文件格式或文件是否损坏。")
                return

            logger.debug(f"图片加载成功 - 原始尺寸: {self.original_pixmap.width()}x{self.original_pixmap.height()}")

            # 检查图片尺寸，过大的图片可能导致内存问题
            max_size = 3000  # 最大尺寸阈值（像素）
            if self.original_pixmap.width() > max_size or self.original_pixmap.height() > max_size:
                # 计算缩放比例
                scale = min(max_size / self.original_pixmap.width(), max_size / self.original_pixmap.height())
                logger.warning(
                    f"图片尺寸过大 ({self.original_pixmap.width()}x{self.original_pixmap.height()})，将自动缩放至 {int(self.original_pixmap.width() * scale)}x{int(self.original_pixmap.height() * scale)}")

                # 自动缩放图片
                self.original_pixmap = self.original_pixmap.scaled(
                    int(self.original_pixmap.width() * scale),
                    int(self.original_pixmap.height() * scale),
                    Qt.KeepAspectRatio,
                    Qt.SmoothTransformation
                )

                QMessageBox.warning(self, "图片尺寸警告",
                                    f"图片尺寸过大 ({self.original_pixmap.width()}x{self.original_pixmap.height()})，已自动缩放至 {int(self.original_pixmap.width() * scale)}x{int(self.original_pixmap.height() * scale)}。\n\n这是为了避免内存问题。")

            # 重置缩放和旋转
            self.scale_factor = 1.0
            self.rotation_angle = 0

            # 更新显示
            self.updateImage()

            # 更新尺寸信息
            self.original_size_label.setText(
                f"原始尺寸: {self.original_pixmap.width()} x {self.original_pixmap.height()}")
            self.updateCurrentSize()

            # 启用缩放和旋转操作
            self.setEnabledActions(True)

            self.statusBar.showMessage(f"已加载图片: {os.path.basename(file_path)}")
        except Exception as e:
            logger.error(f"加载图片时发生错误: {str(e)}")
            self.statusBar.showMessage("加载图片时发生错误", 3000)
            QMessageBox.critical(self, "加载错误", f"加载图片时发生错误:\n{str(e)}")

    def updateImage(self):
        if self.original_pixmap:
            try:
                # 添加调试日志
                logger.debug(f"更新图像 - 缩放因子: {self.scale_factor}, 旋转角度: {self.rotation_angle}")

                # 应用旋转
                transform = QTransform().rotate(self.rotation_angle)
                rotated_pixmap = self.original_pixmap.transformed(transform, Qt.SmoothTransformation)

                logger.debug(f"旋转后尺寸: {rotated_pixmap.width()}x{rotated_pixmap.height()}")

                # 应用缩放
                scaled_pixmap = rotated_pixmap.scaled(
                    int(rotated_pixmap.width() * self.scale_factor),
                    int(rotated_pixmap.height() * self.scale_factor),
                    Qt.KeepAspectRatio,
                    Qt.SmoothTransformation
                )

                logger.debug(f"缩放后尺寸: {scaled_pixmap.width()}x{scaled_pixmap.height()}")

                # 释放之前的像素图资源
                if self.pixmap:
                    self.pixmap = None

                # 更新显示
                self.pixmap = scaled_pixmap
                self.image_label.setPixmap(scaled_pixmap)

                # 更新当前尺寸显示
                self.updateCurrentSize()

                # 更新图像矩形区域，用于坐标系显示
                self.updateImageRect()

                # 触发重绘
                self.image_label.update()
            except Exception as e:
                logger.error(f"更新图像时发生错误: {str(e)}")
                QMessageBox.critical(self, "更新错误", f"更新图像时发生错误:\n{str(e)}")

    def updateImageRect(self):
        if self.pixmap:
            try:
                # 获取标签和图像的尺寸
                label_rect = self.image_label.rect()
                image_rect = self.pixmap.rect()

                # 计算图像在标签中的位置
                x = (label_rect.width() - image_rect.width()) // 2
                y = (label_rect.height() - image_rect.height()) // 2

                # 设置图像矩形区域
                self.image_label.setImageRect(QRect(x, y, image_rect.width(), image_rect.height()))

                # 添加调试日志
                logger.debug(f"图像矩形区域: x={x}, y={y}, width={image_rect.width()}, height={image_rect.height()}")
            except Exception as e:
                logger.error(f"更新图像矩形区域时发生错误: {str(e)}")

    def updateCurrentSize(self):
        if self.pixmap:
            try:
                # 计算当前显示的图片尺寸
                current_width = int(self.original_pixmap.width() * self.scale_factor)
                current_height = int(self.original_pixmap.height() * self.scale_factor)

                # 更新显示
                self.current_size_label.setText(f"当前尺寸: {current_width} x {current_height}")
            except Exception as e:
                logger.error(f"更新当前尺寸时发生错误: {str(e)}")

    def zoom(self, factor):
        # 添加调试日志
        logger.debug(f"缩放操作 - 因子: {factor}, 当前缩放因子: {self.scale_factor}")

        if self.original_pixmap:
            # 限制最小缩放比例，避免图像过小
            if factor < 1 and self.scale_factor * factor < 0.05:
                logger.info("已达到最小缩放比例，无法继续缩小")
                self.statusBar.showMessage("已达到最小缩放比例", 2000)
                return

            # 限制最大缩放比例，避免图像过大
            if factor > 1 and self.scale_factor * factor > 20:
                logger.info("已达到最大缩放比例，无法继续放大")
                self.statusBar.showMessage("已达到最大缩放比例", 2000)
                return

            self.scale_factor *= factor
            self.updateImage()

    def rotate(self, angle):
        # 添加调试日志
        logger.debug(f"旋转操作 - 角度: {angle}")

        if self.original_pixmap:
            self.rotation_angle = (self.rotation_angle + angle) % 360
            self.updateImage()

    def toggleCoordinates(self):
        # 添加调试日志
        logger.debug(f"切换坐标系显示 - 新状态: {not self.image_label.show_coordinates}")

        self.image_label.show_coordinates = not self.image_label.show_coordinates
        self.image_label.update()

    def toggleCrop(self):
        # 添加调试日志
        logger.debug(f"切换裁剪功能 - 新状态: {not self.image_label.crop_enabled}")

        self.image_label.enableCrop(not self.image_label.crop_enabled)
        self.statusBar.showMessage(f"裁剪功能已{'启用' if self.image_label.crop_enabled else '禁用'}")

    def mouseMoveEvent(self, event):
        # 调用 image_label 的 mouseMoveEvent 方法
        if self.image_label:
            self.image_label.mouseMoveEvent(event)

    def cropImage(self):
        logger.debug("进入 cropImage 方法")
        if not self.pixmap or not self.image_label.crop_enabled:
            logger.debug(
                f"检查条件: self.pixmap={bool(self.pixmap)}, self.image_label.crop_enabled={self.image_label.crop_enabled}")
            self.statusBar.showMessage("请先启用裁剪功能并加载图片", 3000)
            logger.debug("退出 cropImage 方法: 条件不满足")
            return

        logger.debug("条件满足: 已加载图片并启用裁剪功能")

        # 获取图像矩形区域
        rect = self.image_label.image_rect
        logger.debug(f"获取图像矩形区域: rect={rect}")
        if not rect:
            logger.debug("退出 cropImage 方法: 图像矩形区域为空")
            return

        # 获取裁剪中心和半径
        crop_center = self.image_label.crop_center
        crop_radius = self.image_label.crop_radius
        logger.debug(f"获取裁剪中心: crop_center={crop_center}, 裁剪半径: crop_radius={crop_radius}")

        # 计算裁剪区域在图像中的位置
        crop_x = crop_center.x() - rect.x()
        crop_y = crop_center.y() - rect.y()
        logger.debug(f"计算裁剪区域坐标: crop_x={crop_x}, crop_y={crop_y}")

        # 创建裁剪区域
        crop_rect = QRect(crop_x - crop_radius, crop_y - crop_radius, crop_radius * 2, crop_radius * 2)
        logger.debug(f"创建裁剪区域: crop_rect={crop_rect}")

        # 计算与图像重叠的有效裁剪区域
        valid_crop_rect = crop_rect.intersected(QRect(0, 0, rect.width(), rect.height()))
        logger.debug(f"调整裁剪区域以确保在图像内: valid_crop_rect={valid_crop_rect}")

        if valid_crop_rect.isEmpty():
            logger.warning("裁剪区域为空，无法裁剪")
            self.statusBar.showMessage("裁剪区域超出图像范围", 3000)
            return

        try:
            # 创建临时画布用于裁剪和应用掩码
            cropped_pixmap = QPixmap(crop_radius * 2, crop_radius * 2)
            cropped_pixmap.fill(Qt.transparent)

            painter = QPainter(cropped_pixmap)
            painter.setRenderHint(QPainter.Antialiasing)

            # 绘制圆形掩码
            path = QPainterPath()
            center = QPoint(crop_radius, crop_radius)  # 裁剪区域中心
            path.addEllipse(center, crop_radius, crop_radius)

            painter.setClipPath(path)

            # 计算源图像中的偏移量（相对于图像矩形）
            source_x = max(0, crop_x - crop_radius)
            source_y = max(0, crop_y - crop_radius)

            # 计算目标图像中的偏移量
            target_x = max(0, crop_radius - crop_x)
            target_y = max(0, crop_radius - crop_y)

            # 计算实际绘制的宽度和高度
            draw_width = min(crop_radius * 2, rect.width() - (crop_x - crop_radius))
            draw_height = min(crop_radius * 2, rect.height() - (crop_y - crop_radius))

            logger.debug(
                f"source_x={source_x}, source_y={source_y}, target_x={target_x}, target_y={target_y}, draw_width={draw_width}, draw_height={draw_height}")

            # 直接从显示的像素图中裁剪
            painter.drawPixmap(target_x, target_y, self.pixmap,
                               source_x,
                               source_y,
                               draw_width, draw_height)

            painter.end()

            # 在右侧面板显示裁剪结果
            self.crop_result_label.setPixmap(cropped_pixmap)

            # 保存裁剪结果供保存使用
            self.cropped_pixmap = cropped_pixmap
            logger.debug("保存裁剪结果到 self.cropped_pixmap")

            # 启用保存按钮
            self.save_button.setEnabled(True)

            self.statusBar.showMessage("图像已裁剪", 3000)
            logger.debug("退出 cropImage 方法")
        except Exception as e:
            logger.error(f"裁剪图像时发生错误: {str(e)}")
            self.statusBar.showMessage("裁剪图像时发生错误", 3000)
            QMessageBox.critical(self, "裁剪错误", f"裁剪图像时发生错误:\n{str(e)}")

    def saveCroppedImage(self):
        # 添加调试日志
        logger.debug("保存裁剪结果操作被触发")

        if not hasattr(self, 'cropped_pixmap') or self.cropped_pixmap is None:
            self.statusBar.showMessage("请先裁剪图像", 3000)
            logger.warning("保存失败: 没有裁剪图像")
            return

        file_path, _ = QFileDialog.getSaveFileName(self, "保存裁剪结果", "",
                                                   "图片文件 (*.png *.jpg *.jpeg)")

        if file_path:
            logger.debug(f"保存路径: {file_path}")

            # 检查文件扩展名以确定格式
            ext = os.path.splitext(file_path)[1].lower()
            if ext == '.png':
                format = 'PNG'
            elif ext in ['.jpg', '.jpeg']:
                format = 'JPEG'
            else:
                format = None  # 使用默认格式

            logger.debug(f"保存格式: {format}")

            try:
                if self.cropped_pixmap.save(file_path, format):
                    self.statusBar.showMessage(f"裁剪结果已保存到: {file_path}", 3000)
                    logger.debug("保存成功")
                else:
                    self.statusBar.showMessage("保存失败", 3000)
                    logger.error("保存失败")
            except Exception as e:
                logger.error(f"保存裁剪结果时发生错误: {str(e)}")
                self.statusBar.showMessage("保存时发生错误", 3000)
                QMessageBox.critical(self, "保存错误", f"保存裁剪结果时发生错误:\n{str(e)}")

    def setEnabledActions(self, enabled):
        # 启用或禁用缩放和旋转操作
        for action in self.findChildren(QAction):
            if action.text() in ["放大", "缩小", "左转", "右转", "裁剪"]:
                action.setEnabled(enabled)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    viewer = ImageViewer()
    viewer.show()
    sys.exit(app.exec_())